package xml.others;

import java.util.HashMap;
import java.util.Map;

import xml.ScannerUIDAbstract;
import xml.elements.InitialState;
import xml.elements.Input;
import xml.elements.Note;
import xml.elements.Output;
import xml.elements.PostCondition;
import xml.elements.PreCondition;
import xml.elements.RegularState;
import xml.elements.RegularTransitionFromOne;
import xml.elements.RegularTransitionFromSet;
import xml.elements.State;
import xml.elements.SubState;
import xml.elements.Text;
import xml.elements.Uid;
import xml.elements.UidCall;
import xml.elements.UnidirectionalTransitionFromOne;
import xml.elements.UnidirectionalTransitionFromSet;

/**
 * <p>
 * Make Valid the ID of Elements. For have equivalence with the transitions.
 * <p>
 * Tornar v�lido o ID dos Elementos. Para ter equival�ncia com as transi��es.
 */

public class IdManager extends ScannerUIDAbstract {

	public static final String DATAITEM = "dataitem";
	public static final String DATAITEMSET = "dataitemset";
	public static final String OPTIONALDATAITEM = "optionaldataitem";
	public static final String STRUCTURE = "structure";
	public static final String STRUCTURESET = "structureset";
	public static final String ENUMERATEDDATA = "enumerateddata";
	public static final String ENUMERATEDOPTION = "enumeratedoption";
	public static final String ORDATAENTRY = "ordataentry";
	public static final String XORDATAENTRY = "xordataentry";
	public static final String OUTPUTDATAITEM = "outputdataitem";
	public static final String OUTPUTDATAITEMSET = "outputdataitemset";
	public static final String OUTPUTSTRUCTURE = "outputstructure";
	public static final String OUTPUTSTRUCTURESET = "outputstructureset";

	private Integer stateID = 0;
	private Integer noteID = 0;
	private Integer postConditionID = 0;
	private Integer preConditionID = 0;
	private Integer transitionID = 0;
	private Integer uidCallID = 0;

	private static IdManager idManager = null;
	private Map<String, Integer> ids = null;

	private IdManager() {
		ids = new HashMap<String, Integer>();
		ids.put(DATAITEM, 0);
		ids.put(OPTIONALDATAITEM, 0);
		ids.put(DATAITEMSET, 0);
		ids.put(STRUCTURE, 0);
		ids.put(STRUCTURESET, 0);
		ids.put(ENUMERATEDDATA, 0);
		ids.put(ENUMERATEDOPTION, 0);
		ids.put(ORDATAENTRY, 0);
		ids.put(XORDATAENTRY, 0);
		ids.put(OUTPUTDATAITEM, 0);
		ids.put(OUTPUTDATAITEMSET, 0);
		ids.put(OUTPUTSTRUCTURE, 0);
		ids.put(OUTPUTSTRUCTURESET, 0);
	}

	public static IdManager getInstance() {
		if (idManager == null) {
			idManager = new IdManager();
		}
		return idManager;
	}

	public static void removeInstance() {
		idManager = null;
	}
	
	/**
	 * Make valid Ids for elementes of Diagram, and return Id of Initial State
	 * 
	 * @param d
	 * @return
	 */
	public void setValidIdsAndFindIdInitialState(Uid d) {

		scanUID(d);

	}

	@Override
	protected void regularStateFound(RegularState o) {
		o.setId("states" + stateID.toString());
		setValidIdsOfSubStatesAndTexts(o);
		stateID = stateID + 1;
	}

	private void setValidIdsOfSubStatesAndTexts(State state) {
		Integer i = 0;
		Integer j = 0;
		for (Object o : state.getInputsOrOutputsOrTexts()) {

			if (o instanceof SubState) {

				((SubState) o).setId("substates" + i.toString());
				i++;
				setValidIdsOfTexts(((SubState) o));
				continue;
			}

			if (o instanceof Text) {

				((Text) o).setId("text" + j.toString());
				j++;

			}

			if (o instanceof Input) {

				((Input) o).setId("input" + j.toString());
				j++;

			}

			if (o instanceof Output) {

				((Output) o).setId("output" + j.toString());
				j++;

			}

		}

	}

	private void setValidIdsOfTexts(SubState substate) {
		Integer i = 0;
		for (Object o : substate.getInputsOrOutputsOrTexts()) {

			if (o instanceof Text) {

				((Text) o).setId("text" + i.toString());
				i++;

			}

			if (o instanceof Input) {

				((Input) o).setId("input" + i.toString());
				i++;

			}

			if (o instanceof Output) {

				((Output) o).setId("output" + i.toString());
				i++;

			}

		}

	}

	@Override
	protected void initialStateFound(InitialState o) {
		o.setId("initialState");
		setValidIdsOfSubStatesAndTexts(o);

	}

	@Override
	protected void noteFound(Note o) {
		o.setId("note" + noteID.toString());
		noteID = noteID + 1;

	}

	@Override
	protected void postConditionFound(PostCondition o) {
		o.setId("postcondition" + postConditionID.toString());
		postConditionID = postConditionID + 1;

	}

	@Override
	protected void preConditionFound(PreCondition o) {
		o.setId("precondition" + preConditionID.toString());
		preConditionID = preConditionID + 1;

	}

	@Override
	protected void regularTransitionFromOneFound(RegularTransitionFromOne o) {
		o.setId("transition" + transitionID.toString());
		transitionID = transitionID + 1;

	}

	@Override
	protected void regularTransitionFromSetFound(RegularTransitionFromSet o) {
		o.setId("transition" + transitionID.toString());
		transitionID = transitionID + 1;

	}

	@Override
	protected void uidCallFound(UidCall o) {
		o.setId("uidcalls" + uidCallID.toString());
		uidCallID = uidCallID + 1;

	}

	@Override
	protected void unidirectionalTransitionFromOneFound(
			UnidirectionalTransitionFromOne o) {
		o.setId("transition" + transitionID.toString());
		transitionID = transitionID + 1;

	}

	@Override
	protected void unidirectionalTransitionFromSetFound(
			UnidirectionalTransitionFromSet o) {
		o.setId("transition" + transitionID.toString());
		transitionID = transitionID + 1;

	}

	public String getId(String item) {
		ids.put(item, ids.get(item) + 1);
		return item + ids.get(item).toString();
	}

}